package com.benzhitech;

import com.benzhitech.config.AppConfig;
import com.benzhitech.config.ConfigLoader;
import com.benzhitech.core.Router;
import com.benzhitech.core.RouteHandler;
import com.benzhitech.core.StaticResourceHandler;
import com.benzhitech.tcp.TcpServer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.buffer.Unpooled;
import io.netty.util.CharsetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.benzhitech.util.ResourceUtil;

/**
 * Tiny 框架启动类
 */
public class TinyApplication {

    private static final Logger log = LoggerFactory.getLogger(TinyApplication.class);

    // 从配置加载端口
    private static int HTTP_PORT;
    private static int TCP_PORT;

    private static Router router;
    private static TcpServer tcpServer;

    public static void main(String[] args) throws Exception {
        // 加载配置
        AppConfig config = ConfigLoader.getConfig();
        HTTP_PORT = config.getHttpPort();
        TCP_PORT = config.getTcpPort();
        
        // 检查静态资源是否存在
        log.info("--- 检查静态资源 ---");
        ResourceUtil.listResources("static");
        ResourceUtil.resourceExists("/static/index.html");
        ResourceUtil.resourceExists("static/index.html");
        ResourceUtil.resourceExists("/static/css/style.css");
        ResourceUtil.resourceExists("static/css/style.css");
        log.info("---------------------");
        
        // 初始化 Router 并添加路由
        router = new Router();
        configureRoutes(router);
        
        // 启动 TCP 服务器
        tcpServer = new TcpServer(TCP_PORT);
        try {
            tcpServer.start();
            log.info("TCP 服务已启动，监听端口: {}", TCP_PORT);
        } catch (Exception e) {
            log.error("TCP 服务启动失败", e);
            throw e;
        }

        // 1. 创建 Boss Group 和 Worker Group
        // Boss Group 只处理连接请求，真正的和客户端业务处理，会交给 Worker Group 完成
        EventLoopGroup bossGroup = new NioEventLoopGroup(1); // 默认线程数是 CPU 核数 * 2
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            // 2. 创建服务器端的启动对象，配置参数
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            log.info("初始化 Channel Pipeline for: {}", ch.remoteAddress());
                            ch.pipeline()
                              .addLast(new HttpServerCodec())
                              .addLast(new HttpObjectAggregator(65536))
                              .addLast(new HttpServerHandler(router));
                        }
                    });

            log.info("Tiny HTTP 服务器准备启动，监听端口: {}", HTTP_PORT);

            // 4. 绑定一个端口并且同步生成了一个 ChannelFuture 对象
            // 启动服务器(并绑定端口)
            ChannelFuture cf = bootstrap.bind(HTTP_PORT).sync();

            log.info("Tiny HTTP 服务器启动成功，监听端口: {}", HTTP_PORT);
            log.info("Tiny 框架初始化完成!");

            // 对关闭通道进行监听
            cf.channel().closeFuture().sync();
        } finally {
            log.info("Tiny HTTP 服务器正在关闭...");
            
            // 关闭 TCP 服务器
            if (tcpServer != null) {
                tcpServer.stop();
            }
            
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
            log.info("Tiny 框架已完全关闭。");
        }
    }

    /**
     * 配置路由规则。
     * 用户可以在这里或专门的配置类中添加路由。
     *
     * @param router Router 实例
     */
    private static void configureRoutes(Router router) {
        // 示例路由：GET /hello
        router.get("/hello", (ctx, request) -> {
            log.info("处理 /hello 请求");
            String msg = "Hello, Tiny World!";
            FullHttpResponse response = new DefaultFullHttpResponse(
                    HttpVersion.HTTP_1_1,
                    HttpResponseStatus.OK,
                    Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8));
            response.headers().set("Content-Type", "text/plain; charset=UTF-8");
            response.headers().set("Content-Length", response.content().readableBytes());
            return response;
        });
        
        // 添加 TCP 相关路由，用于演示 TCP 服务功能
        router.get("/tcp/connections", (ctx, request) -> {
            log.info("获取 TCP 连接列表");
            String[] connectionIds = tcpServer.getActiveConnectionIds();
            int count = tcpServer.getActiveConnectionCount();
            
            StringBuilder sb = new StringBuilder();
            sb.append("当前活跃 TCP 连接: ").append(count).append("\n\n");
            
            if (connectionIds.length > 0) {
                sb.append("连接 ID 列表:\n");
                for (String id : connectionIds) {
                    sb.append("- ").append(id).append("\n");
                }
            } else {
                sb.append("暂无活跃连接");
            }
            
            FullHttpResponse response = new DefaultFullHttpResponse(
                    HttpVersion.HTTP_1_1,
                    HttpResponseStatus.OK,
                    Unpooled.copiedBuffer(sb.toString(), CharsetUtil.UTF_8));
            response.headers().set("Content-Type", "text/plain; charset=UTF-8");
            response.headers().set("Content-Length", response.content().readableBytes());
            return response;
        });

        // 添加静态资源处理路由 - 实际上静态资源在 HttpServerHandler 中会被特殊处理
        // 这里只是添加一个后备路由
        router.get("/static/*", (ctx, request) -> {
            log.info("从路由处理静态资源请求: {}", request.uri());
            return StaticResourceHandler.handleRequest(ctx, request);
        });

        // 不需要为每种文件类型单独添加路由了
        // String[] extensions = {"html", "htm", "css", "js", "json", "jpg", "jpeg", "png", "gif", "ico", "svg"};
        // for (String ext : extensions) {
        //     router.get("/static/*." + ext, (ctx, request) -> {
        //         log.info("处理静态资源请求: {}", request.uri());
        //         return StaticResourceHandler.handleRequest(ctx, request);
        //     });
        // }

        // 添加更多路由...
        // router.get("/users", userController::listUsers);
        // router.post("/users", userController::createUser);
    }
    
    /**
     * 获取 TCP 服务器实例
     * 
     * @return TcpServer 实例
     */
    public static TcpServer getTcpServer() {
        return tcpServer;
    }
} 